package mbp.message;

import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

import mbp.base.MessageType;
import mbp.core.CounterOffer;
import mbp.core.Intention;
import mbp.core.Offer;
import mbp.core.Resource;
import mbp.core.ResourceUtility;
import mbp.core.ResourceValidation;
import mbp.core.Service;
import jade.core.AID;
import jade.lang.acl.ACLMessage;

/**
 * Klasa do budowania i dekodowania wiadomosci przesylanych pomiedzy agentami.
 * Jako nosnik wiadomosci uzywa klasy ACLMessage z pakietu jade.
 * @author Wojciech Wilanski
 *
 */
public class Message
{
	private static String iOntology = "business-platform";
	private boolean isValid;
	private boolean isJadeMgm;
	private String sourceAgent;
	private String destAgent;
	private MessageType messageType;
	private MessageXml contentXml;
	private ObjectBuilder objectBuilder = new ObjectBuilder();
	
	private Logger logger = Logger.getLogger(this.getClass());
	/**
	 * Konstruktor: Tworzenie nowej wadomosci.
	 * @param mType
	 * @param sourceAgent
	 * @param destAgent
	 */
	public Message(MessageType mType, String sourceAgent, String destAgent)
	{
		//super();
		setContentXml(new MessageXml());
		this.sourceAgent = sourceAgent;
		this.destAgent = destAgent;
		//this.messageType = MessageType.valueOf(mType.toString());
		this.messageType = mType;
	}
	
	
	/**
	 * Konstruktor: Odebranie wiadomosci
	 * @param message
	 */
	public Message(ACLMessage message)
	{
		//super();
		setContentXml(new MessageXml());
		
		isJadeMgm = false;
		isValid = false;
		if(message.getOntology().compareTo("JADE-Agent-Management")==0)
		{
			isJadeMgm = true;
			return;
		}		
		if(message.getPerformative() != ACLMessage.INFORM)
		{
			isValid = false;
			logger.error("Performative " + message.getPerformative() + "\n" + message.toString());
			return;
		}
		if(message.getOntology() == null)
		{
			isValid = false;
			logger.error("Ontology " + message.getOntology() + "\n" + message.toString());
			return;
		}
		if(message.getOntology().compareTo(iOntology)!=0)
		{
			isValid = false;
			logger.error("Ontology " + message.getOntology() + "\n" + message.toString());
			return;
		}
		
		messageType = MessageType.valueOf( message.getUserDefinedParameter("type") );
		contentXml.decodeXmlString(message.getContent());
		isValid = true;
	}
	
	public boolean isValid()
	{
		return isValid;
	}
	
	public boolean isJedeMgm()
	{
		return isJadeMgm;
	}

	public MessageXml getContentXml() {
		return contentXml;
	}

	public void setContentXml(MessageXml contentXml) {
		this.contentXml = contentXml;
	}
	
	/**
	 * Zwraca pierwszy obiekt Resource z odebranej wiadomosci (przesylanie zasobow). 
	 * @return
	 */
	public Resource getResource()
	{
		if(contentXml.resources.size()==0)
		{
			return null;
		}
		return objectBuilder.getResource(contentXml.resources.get(0));
	}
	
	/**
	 * Wstawienie do wiadomosci pelnej informacji o zasobie (Przesylanie zasobow).
	 * @param resource
	 */
	public void setResource(Resource resource)
	{
		resource resourceXml = objectBuilder.getResourceInfo(resource);
		contentXml.resources.add(resourceXml);
	}
	
	
	public void setResourceValidation(ResourceValidation rcValidation)
	{	
		validation validationXml = objectBuilder.getValidationInfo(rcValidation);
		contentXml.validations.add(validationXml);
	}
	
	public List<ResourceValidation> getResourceValidation()
	{
		List<ResourceValidation> rcvList = new ArrayList<ResourceValidation>();
		for(int i = 0; i<contentXml.validations.size(); i++)
		{
			ResourceValidation rv = objectBuilder.getResourceValidation(contentXml.validations.get(i));			
			rcvList.add(rv);
		}		
		return rcvList;
	}
	
	/**
	 * Wstawia obiekt Service do wiadomosci
	 * @param service
	 */
	public void setService(Service service)
	{
		contentXml.services.add(objectBuilder.getServiceInfo(service));
	}
	
	public Service getService()
	{
		return objectBuilder.getService(contentXml.services.get(0));
	}
	
	public void setOffer(Offer offer)
	{
		contentXml.offers.add(objectBuilder.getOfferInfo(offer));
	}
	
	public Offer getOffer()
	{
		return objectBuilder.getOffer(contentXml.offers.get(0));
	}
	
	
	public void setIntention(Intention intention)
	{
		contentXml.intentions.add(objectBuilder.getIntentionInfo(intention));
	}
	
	public Intention getIntention()
	{	
		return objectBuilder.getIntention(contentXml.intentions.get(0));
	}
	
	public void setCounterOffer(CounterOffer coffer)
	{
		counteroffer cof = objectBuilder.getCouterOfferInfo(coffer);
		
		contentXml.counteroffers.add(cof);
	}
	
	public CounterOffer getCounterOffer()
	{
		return objectBuilder.getCounterOffer(contentXml.counteroffers.get(0));
	}
	
	public void setResourceUtility(ResourceUtility rcUtility)
	{
		utility utilityXml = objectBuilder.getUtilityInfo(rcUtility);
		contentXml.utilities.add(utilityXml);
	}
	
	public List<ResourceUtility> getResourceUtility()
	{
		List<ResourceUtility> ruList = new ArrayList<ResourceUtility>();
		for(int i = 0; i<contentXml.utilities.size(); i++)
		{
			ResourceUtility ru = objectBuilder.getResourceUtility(contentXml.utilities.get(i));		
			ruList.add(ru);
		}		
		return ruList;
	}
	
	/**
	 * Zwraca gotowy obiekt ACLMessage
	 * @return
	 */
	public ACLMessage GetACLMessage()
	{
		ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
		msg.setOntology(iOntology);
		msg.addReceiver(new AID(destAgent, AID.ISLOCALNAME));
		msg.addUserDefinedParameter("type", messageType.toString());
		msg.setContent(contentXml.getXmlAsString());
		return msg;
	}

	public MessageType getMessageType() 
	{
		return this.messageType; 
	}

}
